package com.shop.cereshop.business.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.shop.cereshop.business.param.customer_service.CustomerServiceAuthState;
import com.shop.cereshop.business.redis.service.api.StringRedisService;
import com.shop.cereshop.business.service.customer_service.CereCustomerServiceConfigService;
import com.shop.cereshop.commons.constant.WxCpConstants;
import com.shop.cereshop.commons.domain.business.CerePlatformBusiness;
import com.shop.cereshop.commons.domain.customer_service.CereCustomerService;
import com.shop.cereshop.commons.domain.customer_service.CereCustomerServiceConfig;
import com.shop.cereshop.commons.domain.customer_service.CereCustomerServiceReceptionist;
import com.shop.cereshop.commons.result.Result;
import com.shop.cereshop.commons.utils.TimeUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpUserService;
import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
import me.chanjar.weixin.cp.bean.WxCpDepart;
import me.chanjar.weixin.cp.bean.WxCpTpDepart;
import me.chanjar.weixin.cp.bean.WxCpTpPreauthCode;
import me.chanjar.weixin.cp.bean.WxCpUser;
import me.chanjar.weixin.cp.constant.WxCpApiPathConsts;
import me.chanjar.weixin.cp.tp.service.WxCpTpService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * 客服
 */
@RestController
@RequestMapping("customerService")
/**
 * 注解方式生成日志对象，指定topic生成对象类名
 */
@Slf4j(topic = "CustomerServiceController")
@Api(value = "客服模块", tags = "客服模块")
public class CustomerServiceController {

    @Autowired
    private CereCustomerServiceConfigService cereCustomerServiceConfigService;

    @Autowired
    private WxCpServiceImpl wxCpServiceImpl;

    @Autowired
    private WxCpUserService wxCpUserService;

    @Autowired
    private WxCpTpService wxCpTpService;

    @Autowired
    private StringRedisService stringRedisService;

    @PostMapping("checkAuthState")
    @ApiOperation("检查是否已授权")
    public Result<CustomerServiceAuthState> checkAuthState(HttpServletRequest request) throws Exception {
        CustomerServiceAuthState authState = new CustomerServiceAuthState();
        try {
            CerePlatformBusiness user = (CerePlatformBusiness) request.getAttribute("user");
            CereCustomerServiceConfig config = cereCustomerServiceConfigService.getByShopId(user.getShopId());
            if (config == null) {
                String now = TimeUtils.yyMMddHHmmss();
                config = new CereCustomerServiceConfig();
                config.setShopId(user.getShopId());
                config.setCreateTime(now);
                config.setUpdateTime(now);
                cereCustomerServiceConfigService.save(config);
            }
            if (StringUtils.isBlank(config.getPermanentCode())) {
                String authPageUrl = generateAuthPageUrl(user.getShopId());
                if (StringUtils.isBlank(authPageUrl)) {
                    authState.setState(3);
                } else {
                    authState.setState(1);
                    authState.setAuthPageUrl(authPageUrl);
                }
            } else {
                authState.setState(2);
            }
        } catch (Exception e) {
            log.error("checkAuthFailed: " + e.getMessage());
        }
        return new Result<>(authState);
    }

    private String generateAuthPageUrl(Long shopId) {
        try {
            String suiteTicket = (String)stringRedisService.get(WxCpConstants.SUITE_TICKET_KEY);
            if (StringUtils.isNotBlank(suiteTicket)) {
                wxCpTpService.setSuiteTicket(suiteTicket);
                String result = wxCpTpService.get(wxCpTpService.getWxCpTpConfigStorage().getApiUrl(WxCpApiPathConsts.Tp.GET_PREAUTH_CODE), null);
                WxCpTpPreauthCode preAuthCode = WxCpTpPreauthCode.fromJson(result);
                log.info("preAuthCode: {}", preAuthCode.getPreAuthCode());
                return WxCpConstants.AUTH_PAGE_PREFIX + "?suite_id=" + wxCpTpService.getWxCpTpConfigStorage().getSuiteId()
                        + "&state=" + shopId + "&pre_auth_code=" + preAuthCode.getPreAuthCode();
            }
        } catch (Exception e) {
            log.error("generateAuthPageUrl: " + e.getMessage(), e);
        }
        return null;
    }

    @PostMapping("getAll")
    @ApiOperation("查询客服列表")
    public Result<List<CereCustomerService>> getAll(HttpServletRequest request) {
        try {
            List<CereCustomerService> resultList = new ArrayList<>();

            String result = wxCpTpService.get(WxCpConstants.API_KF_LIST, "access_token=" + getAccessToken(request));
            JSONObject obj = JSON.parseObject(result);
            if (obj != null) {
                JSONArray array = obj.getJSONArray("account_list");
                if (array != null) {
                    for (int i=0;i<array.size();i++) {
                        JSONObject item = array.getJSONObject(i);
                        CereCustomerService service = new CereCustomerService();
                        String kfId = item.getString("open_kfid");
                        String name = item.getString("name");
                        String avatar = item.getString("avatar");
                        service.setKfId(kfId);
                        service.setName(name);
                        service.setHeadImg(avatar);
                        service.setUrl(WxCpConstants.API_KF_URL + kfId);
                        resultList.add(service);
                    }
                }
            }
            return new Result<>(resultList);
        } catch(Exception e) {
            log.error("getAll: " + e.getMessage(), e);
        }
        return new Result<>(Collections.emptyList());
    }


    @PostMapping("save")
    @ApiOperation("新增客服")
    public Result<Integer> save(@RequestBody CereCustomerService param, HttpServletRequest request) {
        int result = 0;
        try {
            JSONObject obj = new JSONObject();
            obj.put("name", param.getName());
            obj.put("media_id", param.getHeadImg());

            String addResult = wxCpTpService.post(WxCpConstants.API_KF_ADD + "?access_token=" + getAccessToken(request), obj.toJSONString());
            log.info("addResult: {}", addResult);
        } catch (Exception e) {
            log.error("save: " + e.getMessage(), e);
        }
        return new Result<>(result);
    }

    @PostMapping("update")
    @ApiOperation("更新客服")
    public Result<Integer> update(@RequestBody CereCustomerService param, HttpServletRequest request) {
        try {
            JSONObject obj = new JSONObject();
            obj.put("open_kfid", param.getKfId());
            obj.put("name", param.getName());
            obj.put("media_id", param.getHeadImg());
            String addResult = wxCpTpService.post(WxCpConstants.API_KF_UPDATE + "?access_token=" + getAccessToken(request), obj.toJSONString());
            log.info("updateResult: {}", addResult);
        } catch (Exception e) {
            log.error("save: " + e.getMessage(), e);
        }

        int result = 0;
        return new Result<>(result);
    }

    @PostMapping("delete")
    @ApiOperation("删除客服")
    public Result<Integer> delete(@RequestBody CereCustomerService param, HttpServletRequest request) {
        try {
            JSONObject obj = new JSONObject();
            obj.put("open_kfid", param.getKfId());
            String postResult = wxCpTpService.post(WxCpConstants.API_KF_DEL + "?access_token=" + getAccessToken(request), obj.toJSONString());
            log.info("postResult {}", postResult);
        } catch (Exception e) {
            log.error("delete: " + e.getMessage(), e);
        }
        return new Result<>(1);
    }

    @PostMapping("getById")
    @ApiOperation("查询客服")
    public Result<CereCustomerService> getById(@RequestBody CereCustomerService param) {
        //https://qyapi.weixin.qq.com/cgi-bin/kf/account/list?access_token=ACCESS_TOKEN
        //CereCustomerService result = cereCustomerServiceService.getById(param.getId());
        return new Result<>();
    }

    @PostMapping("getAllReceptionist")
    @ApiOperation("查询某个客服下的接待员列表")
    public Result<List<CereCustomerServiceReceptionist>> getAllReceptionist(@RequestBody CereCustomerServiceReceptionist param,
                                                                            HttpServletRequest request) {
        try {
            //String result = wxCpTpService.get(WxCpConstants.API_KF_SERVICER_LIST, "access_token=" + getAccessToken(request) + "&open_kfid=" + param.getKfId(), true);
            String result = wxCpServiceImpl.get(WxCpConstants.API_KF_SERVICER_LIST, "open_kfid=" + param.getKfId());
            if (result != null) {
                JSONObject obj = JSONObject.parseObject(result);
                JSONArray array = obj.getJSONArray("servicer_list");
                if (array != null) {
                    List<CereCustomerServiceReceptionist> list = new ArrayList<>();
                    List<String> userIdList = new ArrayList<>();
                    Map<String, CereCustomerServiceReceptionist> map = new HashMap<>();
                    for (int i=0;i<array.size();i++) {
                        CereCustomerServiceReceptionist item = new CereCustomerServiceReceptionist();
                        JSONObject servicer = array.getJSONObject(i);
                        String userId = servicer.getString("userid");
                        userIdList.add(userId);
                        Integer status = servicer.getInteger("status");
                        item.setKfId(param.getKfId());
                        item.setUserIdList(Collections.singletonList(userId));
                        item.setState(status);
                        list.add(item);
                        map.put(userId, item);
                    }

                    if (userIdList.size() > 0) {
                        //String authCorpId = getCorpId(request);
                        for (String userId:userIdList) {
                            WxCpUser user = wxCpServiceImpl.getUserService().getById(userId);
                            if (user != null) {
                                map.get(userId).setName(user.getName());
                            }
                        }
                    }

                    return new Result<>(list);
                }
            }
        } catch (Exception e) {
            log.error("save: " + e.getMessage(), e);
        }
        return new Result<>();
    }

    @PostMapping("saveReceptionist")
    @ApiOperation("新增接待员")
    public Result<Integer> saveReceptionist(@RequestBody CereCustomerServiceReceptionist param,
                                            HttpServletRequest request) {
        try {
            JSONObject obj = new JSONObject();
            obj.put("open_kfid", param.getKfId());
            obj.put("userid_list", param.getUserIdList());
            String postResult = wxCpServiceImpl.post(WxCpConstants.API_KF_SERVICER_ADD, obj.toJSONString());
            log.info("postResult: {}", postResult);
        } catch (Exception e) {
            log.error("saveReceptionist: " + e.getMessage(), e);
        }
        return new Result<>(1);
    }

    @PostMapping("deleteReceptionist")
    @ApiOperation("删除接待员")
    public Result<Integer> deleteReceptionist(@RequestBody CereCustomerServiceReceptionist param,
                                              HttpServletRequest request) {
        try {
            JSONObject obj = new JSONObject();
            obj.put("open_kfid", param.getKfId());
            obj.put("userid_list", param.getUserIdList());
            String postResult = wxCpServiceImpl.post(WxCpConstants.API_KF_SERVICER_DEL, obj.toJSONString());
            log.info("postResult: {}", postResult);
        } catch (Exception e) {
            log.error("saveReceptionist: " + e.getMessage(), e);
        }
        return new Result<>(1);
    }

    @PostMapping("getDepartmentList")
    @ApiOperation("查询部门")
    public Result<List<WxCpDepart>> getDepartmentList(HttpServletRequest request) {
        try {
            CerePlatformBusiness user = (CerePlatformBusiness) request.getAttribute("user");
            String suiteTicket = (String)stringRedisService.get(WxCpConstants.SUITE_TICKET_KEY);
            wxCpTpService.setSuiteTicket(suiteTicket);

            CereCustomerServiceConfig config = cereCustomerServiceConfigService.getByShopId(user.getShopId());
            List<WxCpTpDepart> departList = wxCpTpService.getWxCpTpDepartmentService().list(config.getAuthCorpId());
            log.info("departList: {}", JSON.toJSONString(departList));
        } catch (Exception e) {
            log.error("wxCpTpService getDepartment: " + e.getMessage(),e);
        }
        try {
            List<WxCpDepart> departmentList = wxCpServiceImpl.getDepartmentService().list(null);
            return new Result<>(departmentList);
        } catch (Exception e) {
            log.error("getDepartmentList: " + e.getMessage(), e);
        }
        return new Result<>();
    }

    @PostMapping("getExternalUserList")
    @ApiOperation("根据部门查询用户")
    public Result<List<WxCpUser>> getUserListByDepartment(@RequestBody WxCpDepart dept) {
        try {
            List<WxCpUser> userList = wxCpUserService.listByDepartment(dept.getId(), true, null);
            return new Result<>(userList);
        } catch (Exception e) {
            log.error("getUserListByDepartment: " + e.getMessage(), e);
        }
        return new Result<>();
    }

    /*@PostMapping("getConfig")
    @ApiOperation("查询客服配置")
    public Result<CereCustomerServiceConfig> getCustomerServiceConfig(HttpServletRequest request) {
        try {
            CerePlatformBusiness user = (CerePlatformBusiness) request.getAttribute("user");
            CereCustomerServiceConfig config = cereCustomerServiceConfigService.getByShopId(user.getShopId());
            //不返回永久授权码 和 授权id
            config.setPermanentCode(null);
            config.setAuthCorpId(null);
            return new Result<>(config);
        } catch (Exception e) {
            log.error("getCustomerServiceConfig: " + e.getMessage(), e);
        }
        return new Result<>();
    }*/

    /*@PostMapping("saveOrUpdateConfig")
    @ApiOperation("新增或修改客服配置")
    public Result<Integer> saveOrUpdateConfig(@RequestBody CereCustomerServiceConfig param, HttpServletRequest request) {
        try {
            CerePlatformBusiness user = (CerePlatformBusiness) request.getAttribute("user");
            param.setShopId(user.getShopId());
            int result = cereCustomerServiceConfigService.saveOrUpdateConfig(param);
            return new Result<>(result);
        } catch (Exception e) {
            log.error("getCustomerServiceConfig: " + e.getMessage(), e);
        }
        return new Result<>();
    }*/

    /**
     * 返回accessToken
     * @param request
     * @return
     * @throws WxErrorException
     */
    private String getAccessToken(HttpServletRequest request) throws WxErrorException {
        CerePlatformBusiness user = (CerePlatformBusiness) request.getAttribute("user");
        String suiteTicket = (String)stringRedisService.get(WxCpConstants.SUITE_TICKET_KEY);
        wxCpTpService.setSuiteTicket(suiteTicket);

        CereCustomerServiceConfig config = cereCustomerServiceConfigService.getByShopId(user.getShopId());
        WxAccessToken corpToken = wxCpTpService.getCorpToken(config.getAuthCorpId(), config.getPermanentCode());
        return corpToken.getAccessToken();
    }

    /**
     * 查询授权corpId
     * @param request
     * @return
     */
    private String getCorpId(HttpServletRequest request) {
        CerePlatformBusiness user = (CerePlatformBusiness) request.getAttribute("user");
        CereCustomerServiceConfig config = cereCustomerServiceConfigService.getByShopId(user.getShopId());
        return config.getAuthCorpId();
    }
}
